#!/usr/bin/env python
################################################################################
#            __  __            _   ____        _ _ ____        _              #
#           |  \/  | ___  __ _| |_| __ )  __ _| | | __ )  ___ | |_           #
#           | |\/| |/ _ \/ _` | __|  _ \ / _` | | |  _ \ / _ \| __|         #
#           | |  | |  __/ (_| | |_| |_) | (_| | | | |_) | (_) | |_          #
#           |_|  |_|\___|\__,_|\__|____/ \__,_|_|_|____/ \___/ \__|          #
#                                                                             #
#                                     by                                       #
# _______ .______       _______  _______   ______   ______   _______   _______  #
#|   ____||   _  \     |   ____||   ____| /      | /  __  \ |       \ |   ____|  #
#|  |__   |  |_)  |    |  |__   |  |__   |  ,----'|  |  |  ||  .--.  ||  |__      #
#|   __|  |      /     |   __|  |   __|  |  |     |  |  |  ||  |  |  ||   __|      #
#|  |     |  |\  \----.|  |____ |  |____ |  `----.|  `--'  ||  '--'  ||  |____      #
#|__|     | _| `._____||_______||_______| \______| \______/ |_______/ |_______|    #
#                                                                                 #
#                        Message Handler Core-Module                             #
#                             Modular FrameWork                                 #
#
# Coders
#
#	Justin Giorgi (rebel_kid)
#
# Debuggers
#
#	Justin Giorgi (rebel_kid)
#	Lachlan Gilmour (chilli0)
#	David Liedle (spiderbyte)
#	(Polarina)
#	(prologic)
#
################################################################################
#                                                                              #
#                               GPL Licensed                                   #
#                                                                              #
################################################################################

# Imports
import time
import traceback

# In Channel message handler
def pubmsg(globalvars, server, event):

	# Creates msg variable holder
	msgvars = {}

	# Message processing
	msgvars["server"] = server
	msgvars["event"] = event
	msgvars["message"] = event.arguments()[0]
	msgvars["source"]  = event.source().split("!")[0]
	msgvars["ident" = event.source().split("!")[1].splite('@')[0]
	msgvars["host"] = event.source().split("!")[1].split('@')[1]
	msgvars["channel"] = event.target()
	msgvars["destination"] = msgvars["channel"]

	# Gets channel id, callsign, and delay
	globalvars["cursor"].execute("select id, callsign, delay from channels where channame = %s", (msgvars["channel"]))
	row = globalvars["cursor"].fetchone()
	if row is not None:
		msgvars["chanid"] = row[0]
		msgvars["call"] = row[1]
		msgvars["delay"] = row[2]
	else:
		globalvars["cursor"].execute("select id, callsign, delay from channels where id = 0")
		row = globalvars["cursor"].fetchone()
		msgvars["chanid"] = row[0]
		msgvars["call"] = row[1]
		msgvars["delay"] = row[2]

	# Gets feature set
	globalvars["cursor"].execute("select * from features where chanid = %s", (msgvars["chanid"]))
	msgvars["features"] = globalvars["cursor"].fetchone()

	# Gets original nick
	if (msgvars["server"], msgvars["source"]) in globalvars["replace"].keys():
		msgvars["nick"] = globalvars["replace"][(msgvars["server"], msgvars["source"])]
	else:
		msgvars["nick"] = msgvars["source"]
		
	# Gets nickid
	if (msgvars["server"], msgvars["host"]) in globalvars["identified"].keys():
		msgvars["nickid"] = globalvars["identified"][(msgvars["server"], msgvars["host"])][0]
		msgvars["botadmin"] = globalvars["identified"][(msgvars["server"], msgvars["host"])][1]
	else:
		msgvars["nickid"] = 0
		msgvars["botadmin"] = 0

	# Gets user permissions	
	globalvars["cursor"].execute("select * from access where nickid = %s and chanid = %s", (msgvars["nickid"], msgvars["chanid"]))
	msgvars["accessperms"] = globalvars["cursor"].fetchone()
	
	# Finds if request is made	
	if msgvars["message"].startswith(msgvars["call"]):

		# Processes message further
		if msgvars["message"].endswith(msgvars["call"]):
			msgvars["message"] = msgvars["message"].strip(msgvars["call"]) + msgvars["call"]
			msgvars["command"] = msgvars["message"].split(' ')
		else:
			msgvars["message"] = msgvars["message"].strip(msgvars["call"])
			msgvars["command"] = msgvars["message"].split(' ')
			
		# Calls the function
		callfunction(globalvars, msgvars)
		
	else:
		
		# Processes message further
		msgvars["command"] = msgvars["message"].split(' ')
		
		# Calls class
		callclass(globalvars, msgvars)
		
	# Calls always functions
	callalways(globalvars, msgvars)

def privmsg(globalvars, server, event):

	# Creates msg variable holder
	msgvars = {}

	# Message processing
	msgvars["server"] = server
	msgvars["event"] = event
	msgvars["source"]  = event.source().split("!")[0]
	msgvars["message"] = event.arguments()[0]
	msgvars["command"] = msgvars["message"].split(' ')
	msgvars["ident" = event.source().split("!")[1].splite('@')[0]
	msgvars["host"] = event.source().split("!")[1].split('@')[1]
	msgvars["destination"] = msgvars["source"]
	
	# Passes to the command handler
	if msgvars["message"].startswith('#'):

		# Strips channel off
		msgvars["channel"] = msgvars["command"][0]
		msgvars["command"] = msgvars["command"][1:]
		
		# Gets channel id, callsign, and delay
		globalvars["cursor"].execute("select id, callsign, delay from channels where channame = %s", (msgvars["channel"]))
		row = globalvars["cursor"].fetchone()
		if row is not None:
			msgvars["chanid"] = row[0]
			msgvars["call"] = row[1]
			msgvars["delay"] = row[2]
		else:
			globalvars["cursor"].execute("select id, callsign, delay from channels where id = 0")
			row = globalvars["cursor"].fetchone()
			msgvars["chanid"] = row[0]
			msgvars["call"] = row[1]
			msgvars["delay"] = row[2]
		
		# Gets feature set
		globalvars["cursor"].execute("select * from features where chanid = %s", (msgvars["chanid"]))
		msgvars["features"] = globalvars["cursor"].fetchone()

		# Gets original nick
		if (msgvars["server"], msgvars["source"]) in globalvars["replace"].keys():
			msgvars["nick"] = globalvars["replace"][(msgvars["server"], msgvars["source"])]
		else:
			msgvars["nick"] = msgvars["source"]
			
		# Gets nickid
		if (msgvars["server"], msgvars["host"]) in globalvars["identified"].keys():
			msgvars["nickid"] = globalvars["identified"][(msgvars["server"], msgvars["host"])][0]
			msgvars["botadmin"] = globalvars["identified"][(msgvars["server"], msgvars["host"])][1]
		else:
			msgvars["nickid"] = 0
			msgvars["botadmin"] = 0
	
		# Gets user permissions	
		globalvars["cursor"].execute("select * from access where nickid = %s and chanid = %s", (msgvars["nickid"], msgvars["chanid"]))
		msgvars["accessperms"] = globalvars["cursor"].fetchone()
		
		# Calls function
		callfunction(globalvars, msgvars)
		
		# Calls always functions
		callalways(globalvars, msgvars)
	
	# Checks if message is a special privmsg function
	else:	
		callprivmsg(globalvars, msgvars)

# Calls the required function to answer a request
def callfunction(globalvars, msgvars):

	# Checks for flooders
	if 'hardcoded-floodprotection' in globalvars["globalalways"].keys():
		approved = globalvars["globalalways"]['hardcoded-floodprotection'](globalvars, msgvars)
	else:
		approved = True

	# Continues if message has been approved
	if approved:
	
		# Notes request in delay dictionary
		globalvars["delays"][msgvars["chanid"]] = time.time()

		# Main try...except
		try:
		
			# Checks if function is loaded
			if msgvars["command"][0].lower() in globalvars["oncall"].keys():
				globalvars["oncall"][msgvars["command"][0].lower()](globalvars, msgvars)
		
			# Checks if load/unload is requested
			elif msgvars["command"][0].lower() == 'load':
				load(globalvars, msgvars)

			elif msgvars["command"][0].lower() == 'unload':
				unload(globalvars, msgvars)
		
			# Passes to factoid handler
			else:
				if "findfactoid" in globalvars["oncall"].keys():
					globalvars["oncall"]["findfactoid"](globalvars, msgvars)
				
				else:
					msgvars["server"].privmsg(msgvars["destination"], "Whoah! Somebody's under the hood messing with my modules. Don't worry they will be back up soon.")
	
		except:
			traceback.print_exc()
			
def callclass(globalvars, msgvars):

	# Main try...except
	try:		
		# Runs local sometimes
		if msgvars["chanid"] in globalvars["localsometimes"].keys():
			globalvars["localsometimes"][msgvars["chanid"]].message(globalvars, msgvars)
		
	except:
		traceback.print_exc()

# Performs global and local always functions
def callalways(globalvars, msgvars):	

	# Main try...except
	try:		
		# Runs all globalalways
		for feature in globalvars["globalalways"].keys():
			if not feature.startswith('hardcoded-'):
				globalvars["globalalways"][feature](globalvars, msgvars)
	
	except:
		traceback.print_exc()
	
def callprivmsg(globalvars, msgvars):	

	# Main try...except
	try:		
		# Calls privmsg function
		if msgvars["command"][0] in globalvars["privmsg"].keys():
			globalvars["privmsg"][msgvars["command"][0]](globalvars, msgvars)
			
		else:
			msgvars["server"].privmsg(msgvars["destination"], "I have no idea what you're talking about.")
	
	except:
		traceback.print_exc()

def autoload(globalvars):
	
	# Loads handlers
	handlers = {'privmsg':privmsg, 'pubmsg':pubmsg}
	for feature in handlers.items():
		if feature[0] not in globalvars["handlers"].keys():
			globalvars["handlers"][feature[0]] = feature[1]
	
def load(globalvars, msgvars):
	
	# Loads handlers
	handlers = {'privmsg':privmsg, 'pubmsg':pubmsg}
	for feature in handlers.items():
		if feature[0] not in globalvars["handlers"].keys():
			globalvars["handlers"][feature[0]] = feature[1]
		else:
			msgvars["server"].privmsg(msgvars["destination"], "There is already a handler for %s." % (feature[0]))
	return True
			
def unload(globalvars, msgvars, reloadmodule = False):
	
	# Unloads handlers
	if reloadmodule:
		handlers = {'privmsg':privmsg, 'pubmsg':pubmsg}
		for feature in handlers.items():
			if feature[0] in globalvars["handlers"].keys():
				del globalvars["handlers"][feature[0]]
			else:
				msgvars["server"].privmsg(msgvars["destination"], "I have no clue what just happened.")
		return True
	else:
		msgvars["server"].privmsg(msgvars["destination"], "You want to unload my what?!?! How bout I just remove your liver.")
		return False
